/*
 * Copyright 2021-2022 the original author and authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.edu.tjnu.tutor.support.controller;

import cn.easyes.core.conditions.LambdaEsQueryWrapper;
import cn.easyes.core.conditions.LambdaEsUpdateWrapper;
import cn.edu.tjnu.tutor.common.annotation.Log;
import cn.edu.tjnu.tutor.common.core.controller.BaseController;
import cn.edu.tjnu.tutor.common.core.domain.AjaxResult;
import cn.edu.tjnu.tutor.common.core.domain.view.PageVO;
import cn.edu.tjnu.tutor.common.validation.groups.Insert;
import cn.edu.tjnu.tutor.common.validation.groups.Update;
import cn.edu.tjnu.tutor.system.domain.dto.ProblemDTO;
import cn.edu.tjnu.tutor.system.domain.model.Answer;
import cn.edu.tjnu.tutor.system.domain.model.Problem;
import cn.edu.tjnu.tutor.system.domain.query.ProblemQuery;
import cn.edu.tjnu.tutor.system.domain.view.ProblemVO;
import cn.edu.tjnu.tutor.system.service.AnswerService;
import cn.edu.tjnu.tutor.system.service.ProblemService;
import cn.edu.tjnu.tutor.system.structure.ProblemStruct;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

import static cn.edu.tjnu.tutor.common.constant.RoleConst.ROLE_STUDENT;
import static cn.edu.tjnu.tutor.common.enums.Category.PROBLEM;
import static cn.edu.tjnu.tutor.common.enums.ExceptionType.USER_IS_NOT_OWNED_PROBLEM;
import static cn.edu.tjnu.tutor.common.enums.OperType.*;

/**
 * 问题信息控制层。
 *
 * @author 王帅
 * @since 1.0
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/problem")
public class ProblemController extends BaseController {

    private final ProblemStruct problemStruct;
    private final AnswerService answerService;
    private final ProblemService problemService;

    /**
     * 查询问题信息。
     *
     * @param query 分页参数
     * @return 分页对象
     */
    @GetMapping("page")
    @Secured(ROLE_STUDENT)
    public AjaxResult<PageVO<ProblemVO>> page(@Validated ProblemQuery query) {
        LambdaEsQueryWrapper<Problem> wrapper = problemService.lambdaQuery()
                .eq(Problem::getUserId, getUserId())
                .eq(Objects.nonNull(query.getScope()), Problem::getScope, query.getScope())
                .eq(Objects.nonNull(query.getStatus()), Problem::getStatus, query.getStatus())
                .match(Objects.nonNull(query.getTitle()), Problem::getTitle, query.getTitle())
                .match(Objects.nonNull(query.getQuestioner()), Problem::getQuestioner, query.getQuestioner())
                .match(Objects.nonNull(query.getCollegeName()), Problem::getCollegeName, query.getCollegeName());
        return pageSuccess(problemService.page(wrapper, query), problemStruct::toVO);
    }

    /**
     * 添加问题信息。
     *
     * @param problemDTO 问题信息
     * @return {@code code = 200} 添加成功，{@code code = 500} 添加失败
     */
    @Secured(ROLE_STUDENT)
    @PostMapping("save")
    @Log(category = PROBLEM, operType = INSERT)
    public AjaxResult<Void> save(@RequestBody @Validated(Insert.class) ProblemDTO problemDTO) {
        return toResult(problemService.save(problemStruct.toEntity(problemDTO, getLoginUser())));
    }

    /**
     * 更新问题信息。
     *
     * @param problemDTO 问题信息
     * @return {@code code = 200} 更新成功，{@code code = 500} 更新失败
     */
    @Secured(ROLE_STUDENT)
    @PutMapping("update")
    @Log(category = PROBLEM, operType = UPDATE)
    public AjaxResult<Void> update(@RequestBody @Validated(Update.class) ProblemDTO problemDTO) {
        LambdaEsUpdateWrapper<Problem> wrapper = problemService.lambdaUpdate()
                .eq(Problem::getUserId, getUserId())
                .eq(Problem::getProblemId, problemDTO.getProblemId());
        return toResult(problemService.update(problemStruct.toEntity(problemDTO), wrapper));
    }

    /**
     * 删除问题信息。
     *
     * @param problemId 问题主键|1
     * @return {@code code = 200} 删除成功，{@code code = 500} 删除失败
     */
    @Secured(ROLE_STUDENT)
    @DeleteMapping("remove/{problemId}")
    @Log(category = PROBLEM, operType = DELETE)
    public AjaxResult<Void> remove(@PathVariable String problemId) {
        LambdaEsQueryWrapper<Problem> wrapper = problemService.lambdaQuery()
                .eq(Problem::getUserId, getUserId())
                .eq(Problem::getProblemId, problemId);
        // 用户没有发布过这个问题
        if (!problemService.exists(wrapper)) {
            return error(USER_IS_NOT_OWNED_PROBLEM);
        }
        // 删除问题答复信息
        answerService.delete(answerService.lambdaQuery()
                .eq(Answer::getProblemId, problemId));
        // 删除问题相关信息
        return toResult(problemService.deleteById(problemId));
    }

}